#include "threadpool.h"
void* ThreadRun( void*arg )
{
	
	CThreadPool* pool = (CThreadPool*)arg;
	while( true )
	{
		pthread_mutex_lock (&pool->m_mutexLock);
		while( pool->m_iQueueSize == 0 && !pool->m_bShutDown )
		{
			printf ("thread 0x%x is waiting\n", pthread_self ());
			pthread_cond_wait (&pool->m_condReady, &pool->m_mutexLock);
		}
		if ( pool->m_bShutDown )
		{
			pthread_mutex_unlock (&pool->m_mutexLock);
			printf ("thread 0x%x will exit\n", pthread_self ());
			pthread_exit (NULL);
		}
		printf ("thread 0x%x is starting to work\n", pthread_self ());
		
		assert (pool->m_iQueueSize != 0);
		assert (pool->m_pWorkQueue!= NULL);

		CWork *worker = pool->m_pWorkQueue;
		pool->m_pWorkQueue = worker->next;
		pthread_mutex_unlock (&pool->m_mutexLock);	
		worker->Run();
		delete worker;
		worker = NULL;
	}
	
	return NULL;	
}

CThreadPool*CThreadPool::m_pThreadPool = NULL;
CWork::CWork( WorkHandler func,void*arg )
{
	m_pHandler = func;
	m_pArg = arg;
	next = NULL;
}

void CWork::Run(  )
{
	m_pHandler( m_pArg );
}

CThreadPool::CThreadPool( )
{
	pthread_mutex_init (&m_mutexLock, NULL);
	pthread_cond_init (&m_condReady, NULL);
	m_bShutDown = false;
	m_iThreadNum = 0;
	//m_inQueue = NULL;
	//m_outQueue = NULL;
	m_pThreadId = NULL;

}
CThreadPool::~CThreadPool()
{
	if ( m_bShutDown )
	{
		return;
	}
	m_bShutDown = false;
	int i = 0;
	pthread_cond_broadcast (&m_condReady);
	
	for (i = 0; i < m_iThreadNum; i++)
		pthread_join (m_pThreadId[i], NULL);
	delete []m_pThreadId;

	CWork* head = NULL;
	while (m_pWorkQueue != NULL)
	{
	head = m_pWorkQueue;
	m_pWorkQueue = m_pWorkQueue->next;
	delete head;
	}
	pthread_mutex_destroy(&m_mutexLock);
	pthread_cond_destroy(&m_condReady);
}

void CThreadPool::SetThreadNum( int num )
{
	m_iThreadNum = num;
	m_pThreadId = new pthread_t[ num ];
	for ( int i = 0;i < num ;i++ )
	{
		pthread_create (&(m_pThreadId[i]), NULL, ThreadRun,NULL);
	}
}
/*
void CThreadPool::SetQueue( CQueue* inQueue,CQueue* outQueue )
{
	m_inQueue = inQueue;
	m_outQueue = outQueue;
}
*/
CThreadPool* CThreadPool::GetInstance()
{
	if ( m_pThreadPool )
	{
		return m_pThreadPool;
	}
	m_pThreadPool = new CThreadPool();
	return m_pThreadPool;
}

void CThreadPool::AddWork( WorkHandler func,void* arg )
{
	CWork* pWork = new CWork( func,arg );
	pthread_mutex_lock (&m_mutexLock);
	CWork* head = m_pWorkQueue;
	if ( head == NULL )
	{
		m_pWorkQueue = pWork;
	}
	else
	{
		while( head->next )head = head->next;
		head->next = pWork;
	}
	 m_iQueueSize++;
   pthread_mutex_unlock (&m_mutexLock);
   pthread_cond_signal (&m_condReady);

}
